package co.fitstart.mobile.web.controller.trading;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.util.WebUtils;

import com.demo2do.core.support.Result;
import com.demo2do.core.utils.JsonUtils;
import com.demo2do.core.wechat.pay.TradeType;
import com.demo2do.core.wechat.pay.WechatWebPayConfig;
import com.demo2do.core.wechat.support.AppType;
import com.demo2do.core.wechat.support.WechatJsConfig;
import com.demo2do.core.wechat.web.handler.JsApiHandler;

import co.fitstart.entity.order.Order;
import co.fitstart.entity.order.PaymentMethod;
import co.fitstart.entity.user.User;
import co.fitstart.mobile.Constant;
import co.fitstart.mobile.entity.UserContext;
import co.fitstart.mobile.handler.PaymentHandler;
import co.fitstart.mobile.service.OrderService;
import co.fitstart.mobile.web.resolver.Secure;

/**
 * 
 * @author mohanlan
 *
 */
@Controller
@RequestMapping("")
public class PaymentController {
    
    private static Logger logger = LoggerFactory.getLogger(PaymentController.class);
    
    private String openidKey = Constant.OPENID_KEY;
    
    @Autowired
    private PaymentHandler paymentHandler;
    
    @Autowired
    private JsApiHandler jsApiHandler;
    
    @Autowired
    private OrderService orderService;
    
    /**
     * 
     * @param userContext
     * @param user
     * @param orderId
     * @param currentUrl
     * @param request
     * @return
     */
    @RequestMapping(value = "/wxpay/prepare", method = RequestMethod.POST)
    public @ResponseBody String wechatpayPrepare(UserContext userContext,
                                                 @Secure User user,
                                                 @RequestParam("orderId") Long orderId,
                                                 @RequestParam("currentUrl") String currentUrl,
                                                 HttpServletRequest request) {

        Result result = new Result();
        
        Order order = orderService.load(Order.class, orderId);
        
        Long userId = user.getId();
        // check order matches user 
        if(!order.matches(userId)) {
            result.fail().message("非法订单");
            return JsonUtils.toJsonString(result);
        }
        
        // Get user's openid
        Cookie cookie = WebUtils.getCookie(request, openidKey);
        String openid = cookie != null ? cookie.getValue() : null;
        logger.trace("PaymentController#wechatpayPrepare() - Get openid [{}] from cookie.", openid);
        
        // Get remote IP address, check NGINX real IP header first
        String xRealIpHeader = request.getHeader("X-Real-IP");  // Only available after NGINX redirect
        String remoteIp = StringUtils.isBlank(xRealIpHeader) ? request.getRemoteAddr() : xRealIpHeader;
        logger.trace("PaymentController#wechatpayPrepare() - Get remote IP address [{}].", remoteIp);
        
        // Construct necessary request data
        Map<String, String> parameters = new HashMap<String, String>();
        parameters.put("total_fee", String.valueOf(order.getPayingPrice()));
        parameters.put("body", order.getProduct().getName());
        parameters.put("spbill_create_ip", remoteIp);
        parameters.put("trade_type", TradeType.JSAPI.toString().toUpperCase());
        parameters.put("openid", openid);
        
        // Request cashier for WeChat prepay id
        Result prepayResult = paymentHandler.preparePay(order.getCode(), String.valueOf(userId), "WECHAT_WEB", parameters);
        
        if (prepayResult.isValid()) {
            
            // Get prepay id and generate JS and pay configuration
            String prepayId = (String) prepayResult.get("prepayId");
            WechatJsConfig jsConfig = jsApiHandler.generateJsConfig(AppType.OFFICIAL, currentUrl);
            WechatWebPayConfig payConfig = jsApiHandler.generateWechatWebPayConfig(AppType.OFFICIAL, prepayId);
            
            if (jsConfig != null && payConfig != null) {
                result.success().data("payConfig", payConfig)
                                .data("jsConfig", jsConfig);
            } else {
                result.fail().message("支付数据生成失败");
            }
        } else {
            result.fail().message(prepayResult.getMessage());
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * 
     * @param userContext
     * @param user
     * @param orderId
     * @param currentUrl
     * @param request
     * @return
     */
    @RequestMapping(value = "/alipay/prepare", method = RequestMethod.POST)
    public @ResponseBody String alipayPrepare(UserContext userContext,
                                              @Secure User user,
                                              @RequestParam("orderId") Long orderId,
                                              @RequestParam("currentUrl") String currentUrl,
                                              HttpServletRequest request) {
        
        Result result = new Result();
        
        Order order = orderService.load(Order.class, orderId);
        
        // check order matches user
        Long userId = user.getId();
        if(!order.matches(userId)) {
            result.fail().message("非法订单");
            return JsonUtils.toJsonString(result);
        }
        
        // Get remote IP address, check NGINX real IP header first
        String xRealIpHeader = request.getHeader("X-Real-IP");  // Only available after NGINX redirect
        String remoteIp = StringUtils.isBlank(xRealIpHeader) ? request.getRemoteAddr() : xRealIpHeader;
        logger.trace("PaymentController#alipayPrepare() - Get remote IP address [{}].", remoteIp);
        
        // Construct necessary request data
        Map<String, String> parameters = new HashMap<String, String>();
        parameters.put("return_url", com.demo2do.core.web.utils.WebUtils.getRealServerPath(request) + "/" + orderId + "/alipay-return");
        parameters.put("subject", order.getProduct().getName());
        parameters.put("total_amount", String.valueOf(order.getPayingPrice()));
        parameters.put("product_code", "QUICK_WAP_PAY");

        // Request cashier for alipay prepay id
        Result prepayResult = paymentHandler.preparePay(order.getCode(), String.valueOf(userId), "ALIPAY_WAP", parameters);
        
        if (prepayResult.isValid()) {
            String form = (String) prepayResult.getData().get("form");
            return form;
            
        } else {
            result.fail().message(prepayResult.getMessage());
            return result.getMessage();
        }
    }
    
    /**
     * 
     * @param orderId
     * @return
     */
    @RequestMapping(value = "{orderId}/alipay-return", method = RequestMethod.GET)
    public ModelAndView alipayReturn(@PathVariable("orderId") Long orderId) {
        ModelAndView modelAndView = new ModelAndView("trading/alipay-return");
        modelAndView.addObject("orderId", orderId);
        return modelAndView;
    }
    
    @RequestMapping(value = "/confirm", method = RequestMethod.POST)
    public @ResponseBody String ConfirmOnlineOrder(@Secure User user,
                                                   @RequestParam("orderId") Long orderId) {

        Result result = new Result();
        
        Order order = orderService.load(Order.class, orderId);
        
        Long userId = user.getId();
        // check order matches user 
        if(!order.matches(userId) || order.getPrice() != 0) {
            result.fail().message("非法订单");
            return JsonUtils.toJsonString(result);
        }
        
        Result prepayResult = paymentHandler.payOrder(order, "ONLINE_YEAR", PaymentMethod.OTHER.toString());
        
        if(prepayResult.isValid()) {
            result.success().message("购买成功");
        } else {
            result.fail().message("购买失败");
        }
        
        return JsonUtils.toJsonString(result);
    }
}
